home *** CD-ROM | disk | FTP | other *** search
/ CU Amiga Super CD-ROM 22 / CU Amiga Magazine's Super CD-ROM 22 (1998)(EMAP Images)(GB)[!][issue 1998-05].iso / PowerPC / Programming / vbcc / machines / ppc / machine.c next >
Encoding:
C/C++ Source or Header  |  1998-02-11  |  60.2 KB  |  1,703 lines

  1. /*  Code generator for a PPC RISC cpu with 32 general purpose,  */
  2. /*  32 floating point and 8 condition code registers.           */
  3.  
  4. #include "supp.h"
  5.  
  6. static char FILE_[]=__FILE__;
  7.  
  8. /*  Public data that MUST be there.                             */
  9.  
  10. /* Name and copyright. */
  11. char cg_copyright[]="vbcc code-generator for PPC V0.2j (c) in 1997-98 by Volker Barthelmann";
  12.  
  13. /*  Commandline-flags the code-generator accepts                */
  14. int g_flags[MAXGF]={VALFLAG,VALFLAG,0,0,0,0,
  15.                     0,0,0,0,0,
  16.                     0};
  17. char *g_flags_name[MAXGF]={"cpu","fpu","const-in-data","sd","merge-constants","fsub-zero",
  18.                            "elf","amiga-align","no-regnames","peephole","setccs",
  19.                            "use-lmw"};
  20. union ppi g_flags_val[MAXGF];
  21.  
  22. /*  Alignment-requirements for all types in bytes.              */
  23. zlong align[16];
  24.  
  25. /*  Alignment that is sufficient for every object.              */
  26. zlong maxalign;
  27.  
  28. /*  CHAR_BIT for the target machine.                            */
  29. zlong char_bit;
  30.  
  31. /*  Tabelle fuer die Groesse der einzelnen Typen                */
  32. zlong sizetab[16];
  33.  
  34. /*  Minimum and Maximum values each type can have.              */
  35. /*  Must be initialized in init_cg().                           */
  36. zlong t_min[32];
  37. zulong t_max[32];
  38.  
  39. /*  Names of all registers.                                     */
  40. char *regnames[MAXR+1]={"noreg",
  41.                         "r0","r1","r2","r10","r9","r8","r7","r6",
  42.                         "r5","r4","r3","r11","r12","r13","r31","r30",
  43.                         "r29","r28","r27","r26","r25","r24","r23","r22",
  44.                         "r21","r20","r19","r18","r17","r16","r15","r14",
  45.                         "f9","f10","f0","f11","f12","f13","f8","f7",
  46.                         "f6","f5","f4","f3","f2","f1","f14","f15",
  47.                         "f16","f17","f18","f19","f20","f21","f22","f23",
  48.                         "f24","f25","f26","f27","f28","f29","f30","f31",
  49.                         "cr0","cr1","cr2","cr3","cr4","cr5","cr6","cr7",
  50.                         "cnt"};
  51.  
  52. /*  The Size of each register in bytes.                         */
  53. zlong regsize[MAXR+1];
  54.  
  55. /*  Type which can store each register. */
  56. struct Typ *regtype[MAXR+1];
  57.  
  58. /*  regsa[reg]!=0 if a certain register is allocated and should */
  59. /*  not be used by the compiler pass.                           */
  60. int regsa[MAXR+1];
  61.  
  62. /*  Specifies which registers may be scratched by functions.    */
  63. int regscratch[MAXR+1]={0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,0,
  64.                           0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
  65.                           1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,0,
  66.                           0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
  67.                           1,1,0,0,0,1,1,1,1};
  68.  
  69. struct reg_handle empty_reg_handle={0,0};
  70.  
  71.  
  72. /****************************************/
  73. /*  Private data and functions.         */
  74. /****************************************/
  75.  
  76. static char *mregnames[MAXR+1];
  77.  
  78. static long malign[16]=  {1,1,2,4,4,4,8,1,4,1,1,1,4,1};
  79. static long msizetab[16]={1,1,2,4,4,4,8,0,4,0,0,0,4,0};
  80.  
  81. static struct Typ ltyp={LONG},ldbl={DOUBLE},lchar={CHAR};
  82.  
  83. static int r0=1;                   /*  special register                    */
  84. static int r2=3;                   /*  reserved or toc                     */
  85. static int r3=11;                  /*  return value                        */
  86. static int sp=2;                   /*  Stackpointer                        */
  87. static int fp=2;                   /*  Framepointer                        */
  88. static int sd=14;                  /*  SmallDataPointer                    */
  89. static int t1=12,t2=13,t3=1;       /*  Temporaries used by code generator  */
  90. static int f1=33,f2=34,f3=35;      /*  Temporaries used by code generator  */
  91. static int cr0=65;                 /*  Default condition-code-register     */
  92.  
  93. #define DATA 0
  94. #define BSS 1
  95. #define CODE 2
  96. #define RODATA 3
  97.  
  98. static int lastlabel;
  99.  
  100. static int section=-1,newobj,crsave;
  101. static char *codename="\t.text\n",*dataname="\t.data\n",*bssname="",*rodataname="\t.section\t.rodata\n";
  102. static int is_const(struct Typ *);
  103. static char *labprefix="l",*idprefix="_";
  104. static long frameoffset,pushed,maxpushed,framesize,localoffset;
  105. static void probj2(FILE *f,struct obj *p,int t);
  106.  
  107. static long real_offset(struct obj *o)
  108. {
  109.   long off;
  110.   if(zl2l(o->v->offset)>=0){
  111.      return zl2l(o->v->offset)+frameoffset+zl2l(o->val.vlong);
  112.   }else{
  113.     return framesize+8-zl2l(o->v->offset)-zl2l(maxalign)+zl2l(o->val.vlong);
  114.   }
  115. }
  116. static long hi(long off)
  117. {
  118.   zlong zl=l2zl(off),r=zlrshift(zl,l2zl(16L));
  119.   if(!zleqto(zland(zl,l2zl(32768L)),l2zl(0L))) r=zladd(r,l2zl(1L));
  120.   return zl2l(zs2zl(zl2zs(zland(r,l2zl(65535L)))));
  121. }
  122. static long lo(long off)
  123. {
  124.   return zl2l(zs2zl(zl2zs(zland(l2zl(off),l2zl(65535L)))));
  125. }
  126. static struct fpconstlist {
  127.   struct fpconstlist *next;
  128.   int label,typ;
  129.   union atyps val;
  130. } *firstfpc;
  131.  
  132. static int addfpconst(struct obj *o,int t)
  133. {
  134.   struct fpconstlist *p=firstfpc;
  135.   t&=NQ;
  136.   if(g_flags[4]&USEDFLAG){
  137.     for(p=firstfpc;p;p=p->next){
  138.       if(t==p->typ){
  139.         eval_const(&p->val,t);
  140.         if(t==FLOAT&&zdeqto(vdouble,zf2zd(o->val.vfloat))) return(p->label);
  141.         if(t==DOUBLE&&zdeqto(vdouble,o->val.vdouble)) return(p->label);
  142.       }
  143.     }
  144.   }
  145.   p=mymalloc(sizeof(struct fpconstlist));
  146.   p->next=firstfpc;
  147.   p->label=++label;
  148.   p->typ=t;
  149.   p->val=o->val;
  150.   firstfpc=p;
  151.   return(p->label);
  152. }
  153.  
  154. #define REG_IND 1
  155. #define IMM_IND 2
  156. #define UPDATE  64
  157.  
  158. static struct obj *cam(int flags,int base,long offset)
  159. /*  Initializes an addressing-mode structure and returns a pointer to   */
  160. /*  that object. Will not survive a second call!                        */
  161. {
  162.   static struct obj obj;
  163.   static struct AddressingMode am;
  164.   obj.am=&am;
  165.   am.flags=flags;
  166.   am.base=base;
  167.   am.offset=offset;
  168.   return(&obj);
  169. }
  170.  
  171. static char *ldt[]={"","bz","ha","wz","wz","fs","fd","","wz","","","","","","","",
  172.                     "","bz","hz","wz","wz"};
  173. static char *sdt[]={"","b","h","w","w","fs","fd","","w","","","","","","","",
  174.                     "","b","h","w","w"};
  175.  
  176. static void load_address(FILE *f,int r,struct obj *o,int typ)
  177. /*  Generates code to load the address of a variable into register r.   */
  178. {
  179.   if(!(o->flags&VAR)) ierror(0);
  180.   if(o->v->storage_class==AUTO||o->v->storage_class==REGISTER){
  181.     long off=real_offset(o);
  182.     if(off<=32767){
  183.       fprintf(f,"\taddi\t%s,%s,%ld\n",mregnames[r],mregnames[sp],off);
  184.     }else{
  185.       fprintf(f,"\taddis\t%s,%s,%ld\n",mregnames[r],mregnames[sp],hi(off));
  186.       fprintf(f,"\taddi\t%s,%s,%ld\n",mregnames[r],mregnames[r],lo(off));
  187.     }
  188.   }else{
  189.     fprintf(f,"\tlis\t%s,",mregnames[r]);
  190.     probj2(f,o,typ);fprintf(f,"@ha\n");
  191.     fprintf(f,"\taddi\t%s,%s,",mregnames[r],mregnames[r]);
  192.     probj2(f,o,typ);fprintf(f,"@l\n");
  193.   }
  194. }
  195. static void load_reg(FILE *f,int r,struct obj *o,int typ,int tmp)
  196. /*  Generates code to load a memory object into register r. tmp is a    */
  197. /*  general purpose register which may be used. tmp can be r.           */
  198. {
  199.   typ&=NU;
  200.   if(o->flags&KONST){
  201.     long l;
  202.     eval_const(&o->val,typ);
  203.     if(typ==FLOAT||typ==DOUBLE){
  204.       int lab;
  205.       if((g_flags[5]&USEDFLAG)&&zdeqto(vdouble,d2zd(0.0))){
  206.         fprintf(f,"\tfsub\t%s,%s,%s\n",mregnames[r],mregnames[r],mregnames[r]);
  207.         return;
  208.       }
  209.       lab=addfpconst(o,typ);
  210.       fprintf(f,"\tlis\t%s,%s%d@ha\n",mregnames[tmp],labprefix,lab);
  211.       fprintf(f,"\tl%s\t%s,%s%d@l(%s)\n",ldt[typ],mregnames[r],labprefix,lab,mregnames[tmp]);
  212.       return;
  213.     }
  214.     l=hi(zl2l(vlong));
  215.     if(l){
  216.       fprintf(f,"\tlis\t%s,%ld\n",mregnames[r],l);
  217.       l=lo(zl2l(vlong));
  218.       if(l) fprintf(f,"\taddi\t%s,%s,%ld\n",mregnames[r],mregnames[r],l);
  219.     }else{
  220.       fprintf(f,"\tli\t%s,%ld\n",mregnames[r],zl2l(vlong));
  221.     }
  222.     return;
  223.   }
  224.   if((o->flags&VAR)&&(o->v->storage_class==EXTERN||o->v->storage_class==STATIC)){
  225.     if(o->flags&VARADR){
  226.       load_address(f,r,o,POINTER);
  227.     }else{
  228.       fprintf(f,"\tlis\t%s,",mregnames[tmp]);
  229.       probj2(f,o,typ);fprintf(f,"@ha\n");
  230.       fprintf(f,"\tl%s\t%s,",ldt[typ],mregnames[r]);
  231.       probj2(f,o,typ);fprintf(f,"@l(%s)\n",mregnames[tmp]);
  232.     }
  233.   }else{
  234.     if((o->flags&(DREFOBJ|REG))==REG){
  235.       if(r!=o->reg)
  236.         fprintf(f,"\t%smr\t%s,%s\n",r>=33?"f":"",mregnames[r],mregnames[o->reg]);
  237.     }else if(!o->am){
  238.       long off=real_offset(o);
  239.       if(off<=32767){
  240.         fprintf(f,"\tl%s\t%s,%ld(%s)\n",ldt[typ],mregnames[r],off,mregnames[sp]);
  241.       }else{
  242.         fprintf(f,"\taddis\t%s,%s,%ld\n",mregnames[r],mregnames[sp],hi(off));
  243.         fprintf(f,"\tl%s\t%s,%ld(%s)\n",ldt[typ],mregnames[r],lo(off),mregnames[r]);
  244.       }
  245.     }else{
  246.       fprintf(f,"\tl%s%s%s\t%s,",ldt[typ],(o->am->flags&UPDATE)?"u":"",(o->am->flags®_IND)?"x":"",mregnames[r]);
  247.       probj2(f,o,typ);fprintf(f,"\n");
  248.     }
  249.   }
  250.   if(typ==CHAR) fprintf(f,"\textsb\t%s,%s\n",mregnames[r],mregnames[r]);
  251. }
  252.  
  253. static void store_reg(FILE *f,int r,struct obj *o,int typ)
  254. /*  Generates code to store register r into memory object o.            */
  255. {
  256.   int tmp;
  257.   typ&=NQ;
  258.   if((o->flags&VAR)&&(o->v->storage_class==EXTERN||o->v->storage_class==STATIC)){
  259.     int tmp=t1;
  260.     if(tmp==r) tmp=t2;
  261.     fprintf(f,"\tlis\t%s,",mregnames[tmp]);
  262.     probj2(f,o,typ);fprintf(f,"@ha\n");
  263.     fprintf(f,"\tst%s\t%s,",sdt[typ],mregnames[r]);
  264.     probj2(f,o,typ);fprintf(f,"@l(%s)\n",mregnames[tmp]);
  265.     return;
  266.   }
  267.   if(!(o->flags&DREFOBJ)&&!o->am){
  268.     long off=real_offset(o);
  269.     if(r==t1) tmp=t2; else tmp=t1;
  270.     if(off<=32767){
  271.       fprintf(f,"\tst%s\t%s,%ld(%s)\n",sdt[typ],mregnames[r],off,mregnames[sp]);
  272.     }else{
  273.       fprintf(f,"\taddis\t%s,%s,%ld\n",mregnames[tmp],mregnames[sp],hi(off));
  274.       fprintf(f,"\tst%s\t%s,%ld(%s)\n",sdt[typ],mregnames[r],lo(off),mregnames[tmp]);
  275.     }
  276.   }else{
  277.     if(!o->am){
  278.       fprintf(f,"\tst%s\t%s,",sdt[typ],mregnames[r]);
  279.       probj2(f,o,typ);fprintf(f,"\n");
  280.     }else{
  281.       fprintf(f,"\tst%s%s%s\t%s,",sdt[typ],(o->am->flags&UPDATE)?"u":"",(o->am->flags®_IND)?"x":"",mregnames[r]);
  282.       probj2(f,o,typ);fprintf(f,"\n");
  283.     }
  284.   }
  285. }
  286.  
  287. static long pof2(zulong x)
  288. /*  Yields log2(x)+1 oder 0. */
  289. {
  290.   zulong p;int ln=1;
  291.   p=ul2zul(1L);
  292.   while(ln<=32&&zulleq(p,x)){
  293.     if(zuleqto(x,p)) return(ln);
  294.     ln++;p=zuladd(p,p);
  295.   }
  296.   return(0);
  297. }
  298.  
  299. static char *dct[]={"","byte","uahalf","uaword","uaword","uaword","uaword"};
  300. static struct IC *do_refs(FILE *,struct IC *);
  301. static void pr(FILE *,struct IC *);
  302. static void function_top(FILE *,struct Var *,long);
  303. static void function_bottom(FILE *f,struct Var *,long);
  304.  
  305. #define isreg(x) ((p->x.flags&(REG|DREFOBJ))==REG)
  306.  
  307. static int q1reg,q2reg,zreg;
  308.  
  309. static char *ccs[]={"eq","ne","lt","ge","le","gt",""};
  310. static char *logicals[]={"or","xor","and"};
  311. static char *record[]={"","."};
  312. static char *arithmetics[]={"slw","srw","add","sub","mullw","divw","mod"};
  313. static char *isimm[]={"","i"};
  314.  
  315. static struct IC *do_refs(FILE *f,struct IC *p)
  316. /*  Does some pre-processing like fetching operands from memory to      */
  317. /*  registers etc.                                                      */
  318. {
  319.   int typ=p->typf,typ1,reg,c=abs(p->code);
  320.  
  321.   if(c==CONVCHAR) typ=CHAR;
  322.   if(c==CONVUCHAR) typ=UNSIGNED|CHAR;
  323.   if(c==CONVSHORT) typ=SHORT;
  324.   if(c==CONVUSHORT) typ=UNSIGNED|SHORT;
  325.   if(c==CONVINT) typ=LONG;
  326.   if(c==CONVUINT) typ=UNSIGNED|LONG;
  327.   if(c==CONVLONG) typ=LONG;
  328.   if(c==CONVULONG) typ=UNSIGNED|LONG;
  329.   if(c==CONVFLOAT) typ=FLOAT;
  330.   if(c==CONVDOUBLE) typ=DOUBLE;
  331.   if(c==CONVPOINTER) typ=UNSIGNED|LONG;
  332.   if((typ&NQ)==POINTER) typ=UNSIGNED|LONG;
  333.  
  334.   if((c==SUB||c==SUBIFP)&&(p->q2.flags&(KONST|DREFOBJ))==KONST&&(typ&NQ)<=LONG){
  335.     eval_const(&p->q2.val,typ);
  336.     if(zlleq(vlong,l2zl(32768L))&&zlleq(l2zl(-32767L),vlong)){
  337.       union atyps val;
  338.       if(c==SUB){
  339.         if(p->code==SUB) p->code=c=ADD; else p->code=c=-ADD;
  340.       }else{
  341.         if(p->code==SUBIFP) p->code=c=ADDI2P; else p->code=c=-ADDI2P;
  342.       }
  343.       c=abs(c);
  344.       val.vlong=zlsub(l2zl(0L),vlong);
  345.       eval_const(&val,LONG);
  346.       insert_const2(&p->q2.val,typ);
  347.       p->typf=typ=(typ&~UNSIGNED);
  348.     }
  349.   }
  350.  
  351.   q1reg=q2reg=zreg=0;
  352.   if(p->q1.flags®) q1reg=p->q1.reg;
  353.   if(p->q2.flags®) q2reg=p->q2.reg;
  354.   if((p->z.flags&(REG|DREFOBJ))==REG) zreg=p->z.reg;
  355.  
  356.   if((p->q1.flags&(KONST|DREFOBJ))==KONST){
  357.     eval_const(&p->q1.val,typ);
  358.     if((typ&NQ)==FLOAT||(typ&NQ)==DOUBLE) reg=f1; else reg=t1;
  359.     if(c==ASSIGN&&zreg) reg=zreg;
  360.     if(c==SETRETURN&&p->z.reg) reg=p->z.reg;
  361.     if(c!=SUB||(typ&NQ)>LONG||!zlleq(vlong,l2zl(32767L))||!zlleq(l2zl(-32768L),vlong)){
  362.       load_reg(f,reg,&p->q1,typ,t1);
  363.       q1reg=reg;
  364.     }
  365.   }else if(c!=ADDRESS){
  366.     if((typ&NQ)==FLOAT||(typ&NQ)==DOUBLE) reg=f1; else reg=t1;
  367.     if((c==ASSIGN||(c>=CONVCHAR&&c<=CONVULONG&&c!=CONVFLOAT&&c!=CONVDOUBLE))&&zreg>=1&&zreg<=32) reg=zreg;
  368.     if(c==SETRETURN&&p->z.reg) reg=p->z.reg;
  369.     if(p->q1.am){
  370.       load_reg(f,reg,&p->q1,typ,t1);
  371.       q1reg=reg;
  372.     }else{
  373.       if(p->q1.flags&&!q1reg){
  374.         if(p->q1.flags&DREFOBJ) {typ1=POINTER;reg=t1;} else typ1=typ;
  375.         if((typ1&NQ)<=POINTER){
  376.           int m=p->q1.flags;
  377.           p->q1.flags&=~DREFOBJ;
  378.           load_reg(f,reg,&p->q1,typ1,t1);
  379.           p->q1.flags=m;
  380.           q1reg=reg;
  381.         }
  382.       }
  383.       if((p->q1.flags&DREFOBJ)&&(typ&NQ)<=POINTER){
  384.         if((typ&NQ)==FLOAT||(typ&NQ)==DOUBLE) reg=f1; else reg=t1;
  385.         if((c==ASSIGN||(c>=CONVCHAR&&c<=CONVULONG&&c!=CONVFLOAT&&c!=CONVDOUBLE))&&zreg>=1&&zreg<=32) reg=zreg;
  386.         if(c==SETRETURN&&p->z.reg) reg=p->z.reg;
  387.         if(p->q1.am)
  388.           load_reg(f,reg,&p->q1,typ,t1);
  389.         else
  390.           load_reg(f,reg,cam(IMM_IND,q1reg,0),typ,t1);
  391.         q1reg=reg;
  392.       }
  393.     }
  394.   }
  395.   typ=p->typf;
  396.   if((p->q2.flags&(KONST|DREFOBJ))==KONST){
  397.     eval_const(&p->q2.val,typ);
  398.     if((typ&NQ)==FLOAT||(typ&NQ)==DOUBLE) reg=f2; else reg=t2;
  399.     if((typ&NQ)==FLOAT||(typ&NQ)==DOUBLE||c==DIV||c==SUB||c==MOD){
  400.       load_reg(f,reg,&p->q2,typ,t2);
  401.       q2reg=reg;
  402.     }else{
  403.       if((c>=OR&&c<=AND)||(c==COMPARE&&(typ&UNSIGNED))){
  404.         if(!zulleq(vulong,ul2zul(65535UL))){
  405.           load_reg(f,reg,&p->q2,typ,t2);
  406.           q2reg=reg;
  407.         }
  408.       }else{
  409.         if(!zlleq(vlong,l2zl(32767L))||!zlleq(l2zl(-32768L),vlong)){
  410.           load_reg(f,reg,&p->q2,typ,t2);
  411.           q2reg=reg;
  412.         }
  413.       }
  414.     }
  415.   }else{
  416.     if(p->q2.am){
  417.       if((typ&NQ)==FLOAT||(typ&NQ)==DOUBLE) reg=f2; else reg=t2;
  418.       load_reg(f,reg,&p->q2,typ,t2);
  419.       q2reg=reg;
  420.     }else{
  421.       if(p->q2.flags&&!q2reg){
  422.         if((p->q2.flags&DREFOBJ)) typ1=POINTER; else typ1=typ;
  423.         if((typ1&NQ)==FLOAT||(typ1&NQ)==DOUBLE) reg=f2; else reg=t2;
  424.         if((typ1&NQ)<=POINTER){
  425.           int m=p->q2.flags;
  426.           p->q2.flags&=~DREFOBJ;
  427.           load_reg(f,reg,&p->q2,typ1,t2);
  428.           p->q2.flags=m;
  429.           q2reg=reg;
  430.         }
  431.       }
  432.       if((p->q2.flags&DREFOBJ)&&(typ&NQ)<=POINTER){
  433.         if((typ&NQ)==FLOAT||(typ&NQ)==DOUBLE) reg=f2; else reg=t2;
  434.         if(p->q2.am)
  435.           load_reg(f,reg,&p->q2,typ,t2);
  436.         else
  437.           load_reg(f,reg,cam(IMM_IND,q2reg,0),typ,t2);
  438.         q2reg=reg;
  439.       }
  440.     }
  441.   }
  442.   if(p->z.am||(p->z.flags&&!isreg(z))){
  443.     typ=p->typf;
  444.     if((typ&NQ)==FLOAT||(typ&NQ)==DOUBLE) zreg=f3; else zreg=t3;
  445.   }
  446.   if(q1reg){ p->q1.flags=REG; p->q1.reg=q1reg;p->q1.am=0;}
  447.   if(q2reg){ p->q2.flags=REG; p->q2.reg=q2reg;p->q2.am=0;}
  448.   return(p);
  449. }
  450. static void pr(FILE *f,struct IC *p)
  451.      /*  Writes the destination register to the real destination if necessary.   */
  452. {
  453.   int typ=p->typf;
  454.   if(p->code==ADDRESS) typ=POINTER;
  455.   if(p->z.flags){
  456.     if(p->z.am){
  457.       store_reg(f,zreg,&p->z,typ);
  458.     }else if(!isreg(z)){
  459.       if(p->z.flags&DREFOBJ){
  460.         if(p->z.flags®){
  461.           if(p->z.am)
  462.             store_reg(f,zreg,&p->z,typ);
  463.           else
  464.             store_reg(f,zreg,cam(IMM_IND,p->z.reg,0),typ);
  465.         }else{
  466.           int r;
  467.           if(t1==zreg) r=t2; else r=t1;
  468.           load_reg(f,r,&p->z,POINTER,r);
  469.           store_reg(f,zreg,cam(IMM_IND,r,0),typ);
  470.         }
  471.       }else{
  472.         store_reg(f,zreg,&p->z,typ);
  473.       }
  474.     }else{
  475.       if(p->z.reg!=zreg)
  476.         fprintf(f,"\t%smr\t%s,%s\n",zreg>=33?"f":"",mregnames[p->z.reg],mregnames[zreg]);
  477.     }
  478.   }
  479. }
  480.  
  481. static void probj2(FILE *f,struct obj *p,int t)
  482. /*  Prints an object.                               */
  483. {
  484.   if(p->am){
  485.     if(p->am->flags®_IND) fprintf(f,"%s,%s",mregnames[p->am->offset],mregnames[p->am->base]);
  486.     if(p->am->flags&IMM_IND) fprintf(f,"%ld(%s)",p->am->offset,mregnames[p->am->base]);
  487.     return;
  488.   }
  489.   /*  if(p->flags&DREFOBJ) fprintf(f,"(");*/
  490.   if(p->flags&VAR) {
  491.     if(p->v->storage_class==AUTO||p->v->storage_class==REGISTER){
  492.       if(p->flags®){
  493.         fprintf(f,"%s",mregnames[p->reg]);
  494.       }else{
  495.         fprintf(f,"%ld(%s)",real_offset(p),mregnames[sp]);
  496.       }
  497.     }else{
  498.       if(!zleqto(l2zl(0L),p->val.vlong)){printval(f,&p->val,LONG,0);fprintf(f,"+");}
  499.       if(p->v->storage_class==STATIC&&(p->v->vtyp->flags&NQ)!=FUNKT){
  500.         fprintf(f,"%s%ld",labprefix,zl2l(p->v->offset));
  501.       }else{
  502.         fprintf(f,"%s%s",idprefix,p->v->identifier);
  503.       }
  504.     }
  505.   }
  506.   if((p->flags®)&&!(p->flags&VAR)) fprintf(f,"%s",mregnames[p->reg]);
  507.   if(p->flags&KONST){
  508.     printval(f,&p->val,t&NU,0);
  509.   }
  510.   /*  if(p->flags&DREFOBJ) fprintf(f,")");*/
  511. }
  512. static int exists_freereg(struct IC *p,int reg)
  513. /*  Test if there is a sequence of FREEREGs containing FREEREG reg. */
  514. {
  515.   while(p&&(p->code==FREEREG||p->code==ALLOCREG)){
  516.     if(p->code==FREEREG&&p->q1.reg==reg) return 1;
  517.     p=p->next;
  518.   }
  519.   return 0;
  520. }
  521.  
  522. static size_t lsize;
  523. static unsigned char *once,*twice;
  524.  
  525. static void peephole(struct IC *p)
  526. /* Try to use addressing modes */
  527. {
  528.   int c,c2,r,cnt;struct IC *p2;struct AddressingMode *am;
  529.   lsize=((label-lastlabel+1+7)/CHAR_BIT)*CHAR_BIT;
  530.   once=mymalloc(lsize);
  531.   twice=mymalloc(lsize);
  532.   memset(once,0,lsize);
  533.   memset(twice,0,lsize);
  534.   for(;p;p=p->next){
  535.     c=p->code;
  536.     /* Test which labels are jumped to more than once. */
  537.     if(c>=BEQ&&c<=BRA){
  538.       if(BTST(once,p->typf-lastlabel))
  539.         BSET(twice,p->typf-lastlabel);
  540.       else
  541.         BSET(once,p->typf-lastlabel);
  542.     }
  543.     /* Try test-opt */
  544.     if(c==TEST&&!(p->q1.flags&DREFOBJ)){
  545.       for(p2=p->prev;p2;p2=p2->prev){
  546.         c2=p2->code;
  547.         if(c2==NOP||c2==ALLOCREG||c2==FREEREG) continue;
  548.         if(c2==CALL||(c2>=LABEL&&c2<=BRA)) break;
  549.         if((p2->z.flags&DREFOBJ)&&(p->q1.flags&(REG|DREFOBJ))!=REG) break;
  550.         if(p->q1.flags==p2->z.flags&&p->q1.am==p2->z.am){
  551.           if(!(p->q1.flags&VAR)||(p->q1.v==p2->z.v&&zleqto(p->q1.val.vlong,p2->z.val.vlong))){
  552.             if(!(p->q1.flags®)||p->q1.reg==p2->z.reg){
  553.               if(p->z.flags==0||(isreg(z)&&p->z.reg==cr0)){
  554.                 if(p->typf==p2->typf&&(!(p->typf&UNSIGNED)||!multiple_ccs)){
  555.                   p2->code=-p2->code; /* mark it */
  556.                 }
  557.                 break;
  558.               }
  559.             }
  560.           }
  561.         }
  562.       }
  563.     }
  564.     /* Try update */
  565.     if((c==ADDI2P||c==SUBIFP)&&isreg(q1)&&isreg(z)&&p->q1.reg==p->z.reg){
  566.       if((p->q2.flags&(KONST|DREFOBJ))==KONST){
  567.         eval_const(&p->q2.val,p->typf);
  568.         if(c==SUBIFP) vlong=zlsub(l2zl(0L),vlong);
  569.         if(zlleq(l2zl(-32768L),vlong)&&zlleq(vlong,l2zl(32767L))){
  570.           struct obj *o;
  571.           r=p->q1.reg;cnt=0;o=0;
  572.           for(p2=p->next;p2;p2=p2->next){
  573.             c2=p2->code;
  574.             if(c2==NOP||c2==ALLOCREG||c2==FREEREG) continue;
  575.             if((c2==CALL&®scratch[r])||(c2>=LABEL&&c2<=BRA)) break;
  576.             if((p2->q1.flags&(DREFOBJ|REG))==REG&&p2->q1.reg==r) break;
  577.             if((p2->q2.flags&(DREFOBJ|REG))==REG&&p2->q2.reg==r) break;
  578.             if((p2->z.flags&(DREFOBJ|REG))==REG&&p2->z.reg==r) break;
  579.             if((p2->q1.flags&(REG|DREFOBJ))==(REG|DREFOBJ)&&p2->q1.reg==r){o=&p2->q1;cnt++;}
  580.             if((p2->q2.flags&(REG|DREFOBJ))==(REG|DREFOBJ)&&p2->q2.reg==r){o=&p2->q2;cnt++;}
  581.             if((p2->z.flags&(REG|DREFOBJ))==(REG|DREFOBJ)&&p2->z.reg==r){o=&p2->z;cnt++;}
  582.             if(cnt>1) break;
  583.             if(cnt==1){
  584.               if(p2->code==ASSIGN&&((p2->typf&NQ)>POINTER||!zleqto(p2->q2.val.vlong,sizetab[p2->typf&NQ])))
  585.                 break;
  586.               o->am=am=mymalloc(sizeof(*am));
  587.               o->am->flags=(IMM_IND|UPDATE);
  588.               o->am->base=r;
  589.               o->am->offset=zl2l(vlong);
  590.               p->code=NOP;
  591.               continue;
  592.             }
  593.           }
  594.         }
  595.       }
  596.     }
  597.     /* Try const(reg) */
  598.     if((c==ADDI2P||c==SUBIFP)&&(p->q2.flags&(KONST|DREFOBJ))==KONST&&isreg(z)){
  599.       int base;zlong of;
  600.       p2=p->next;
  601.       while(p2&&(p2->code==FREEREG||p2->code==ALLOCREG)) p2=p2->next;
  602.       if(p2) c2=p2->code; else c2=0;
  603.       eval_const(&p->q2.val,p->typf);
  604.       if(c==SUBIFP) of=zlsub(l2zl(0L),vlong); else of=vlong;
  605.       r=p->z.reg;
  606.       if(isreg(q1)) base=p->q1.reg; else base=r;
  607.       if(c2&&zlleq(l2zl(-32768L),of)&&zlleq(of,l2zl(32767L))&&c2!=CALL&&(c2<LABEL||c2>BRA)
  608.          &&(c2!=ASSIGN||((p2->typf&NQ)<=POINTER&&zleqto(p2->q2.val.vlong,sizetab[p2->typf&NQ])))
  609.          &&c2!=ADDRESS&&exists_freereg(p2->next,r)){
  610.         if(((p2->q1.flags&(REG|DREFOBJ))!=REG||p2->q1.reg!=r)
  611.            &&((p2->q2.flags&(REG|DREFOBJ))!=REG||p2->q2.reg!=r)){
  612.           cnt=0;
  613.           if((p2->q1.flags&(REG|DREFOBJ))==(REG|DREFOBJ)&&p2->q1.reg==r){
  614.             p2->q1.am=am=mymalloc(sizeof(*am));
  615.             p2->q1.am->flags=IMM_IND;
  616.             p2->q1.am->base=base;
  617.             p2->q1.am->offset=zl2l(of);
  618.             cnt++;
  619.           }
  620.           if((p2->q2.flags&(REG|DREFOBJ))==(REG|DREFOBJ)&&p2->q2.reg==r){
  621.             p2->q2.am=am=mymalloc(sizeof(*am));
  622.             p2->q2.am->flags=IMM_IND;
  623.             p2->q2.am->base=base;
  624.             p2->q2.am->offset=zl2l(of);
  625.             cnt++;
  626.           }
  627.           if((p2->z.flags&(REG|DREFOBJ))==(REG|DREFOBJ)&&p2->z.reg==r){
  628.             p2->z.am=am=mymalloc(sizeof(*am));
  629.             p2->z.am->flags=IMM_IND;
  630.             p2->z.am->base=base;
  631.             p2->z.am->offset=zl2l(of);
  632.             cnt++;
  633.           }
  634.           if(isreg(q1)){
  635.             p->code=NOP;p->q1.flags=p->q2.flags=p->z.flags=0;
  636.           }else{
  637.             p->code=ASSIGN;p->q2.flags=0;
  638.           }
  639.           if(cnt==1){
  640.             /* Can we use update? */
  641.             p2=p2->next;
  642.             while(p2&&(p2->code==FREEREG||p2->code==ALLOCREG)) p2=p2->next;
  643.             if(p2){
  644.               c2=p2->code;
  645.               if(c2==ADDI2P||c2==SUBIFP){
  646.                 if((p2->q1.flags&(REG|DREFOBJ))==REG&&p2->q1.reg==base
  647.                    &&(p2->z.flags&(REG|DREFOBJ))==REG&&p2->z.reg==base
  648.                    &&(p2->q2.flags&(KONST|DREFOBJ))==KONST ){
  649.                   eval_const(&p2->q2.val,p2->typf);
  650.                   if(c2==SUBIFP) vlong=zlsub(l2zl(0L),vlong);
  651.                   if(zleqto(vlong,of)){
  652.                     am->flags|=UPDATE;
  653.                     p2->code=NOP;
  654.                   }
  655.                 }
  656.               }
  657.             }
  658.           }
  659.           continue;
  660.         }
  661.       }
  662.     }
  663.     /* Try reg,reg */
  664.     if(c==ADDI2P&&isreg(q2)&&isreg(z)&&p->q2.reg!=p->z.reg){
  665.       int base,idx;
  666.       p2=p->next;
  667.       while(p2&&(p2->code==FREEREG||p2->code==ALLOCREG)) p2=p2->next;
  668.       if(p2) c2=p2->code; else c2=0;
  669.       r=p->z.reg;idx=p->q2.reg;
  670.       if(isreg(q1)) base=p->q1.reg; else base=r;
  671.       if(c2&&c2!=CALL&&(c2<LABEL||c2>BRA)
  672.          &&(c2!=ASSIGN||((p2->typf&NQ)<=POINTER&&zleqto(p2->q2.val.vlong,sizetab[p2->typf&NQ])))
  673.          &&c2!=ADDRESS&&exists_freereg(p2->next,r)){
  674.         if(((p2->q1.flags&(REG|DREFOBJ))!=REG||p2->q1.reg!=r)
  675.            &&((p2->q2.flags&(REG|DREFOBJ))!=REG||p2->q2.reg!=r) ){
  676.           cnt=0;
  677.           if((p2->q1.flags&(REG|DREFOBJ))==(REG|DREFOBJ)&&p2->q1.reg==r){
  678.             p2->q1.am=am=mymalloc(sizeof(*am));
  679.             p2->q1.am->flags=REG_IND;
  680.             p2->q1.am->base=base;
  681.             p2->q1.am->offset=idx;
  682.             cnt++;
  683.           }
  684.           if((p2->q2.flags&(REG|DREFOBJ))==(REG|DREFOBJ)&&p2->q2.reg==r){
  685.             p2->q2.am=am=mymalloc(sizeof(*am));
  686.             p2->q2.am->flags=REG_IND;
  687.             p2->q2.am->base=base;
  688.             p2->q2.am->offset=idx;
  689.             cnt++;
  690.           }
  691.           if((p2->z.flags&(REG|DREFOBJ))==(REG|DREFOBJ)&&p2->z.reg==r){
  692.             p2->z.am=am=mymalloc(sizeof(*am));
  693.             p2->z.am->flags=REG_IND;
  694.             p2->z.am->base=base;
  695.             p2->z.am->offset=idx;
  696.             cnt++;
  697.           }
  698.           if(isreg(q1)){
  699.             p->code=NOP;p->q1.flags=p->q2.flags=p->z.flags=0;
  700.           }else{
  701.             p->code=ASSIGN;p->q2.flags=0;
  702.           }
  703.           if(cnt==1){
  704.             /* Can we use update? */
  705.             p2=p2->next;
  706.             while(p2&&(p2->code==FREEREG||p2->code==ALLOCREG)) p2=p2->next;
  707.             if(p2){
  708.               c2=p2->code;
  709.               if(c2==ADDI2P){
  710.                 if((p2->q1.flags&(REG|DREFOBJ))==REG&&p2->q1.reg==base
  711.                    &&(p2->z.flags&(REG|DREFOBJ))==REG&&p2->z.reg==base
  712.                    &&(p2->q2.flags&(REG|DREFOBJ))==REG&&p2->q2.reg==idx){
  713.                   am->flags|=UPDATE;
  714.                   p2->code=NOP;
  715.                 }
  716.               }
  717.             }
  718.           }
  719.           continue;
  720.         }
  721.       }
  722.     }
  723.   }
  724. }
  725.  
  726. static int stmw,stme;
  727.  
  728. static void function_top(FILE *f,struct Var *v,long offset)
  729. /*  Generates function top.                             */
  730. {
  731.   int i,preg;long of;
  732.   if(section!=CODE){fprintf(f,codename);section=CODE;}
  733.   if(v->storage_class==EXTERN) fprintf(f,"\t.global\t%s%s\n",idprefix,v->identifier);
  734.   fprintf(f,"\t.align\t4\n%s%s:\n",idprefix,v->identifier);
  735.   frameoffset=8+maxpushed;
  736.   framesize=frameoffset+offset;
  737.   stmw=0;stme=0;
  738.   for(i=1;i<=64;i++){
  739.     if(regused[i]&&!regscratch[i]&&!regsa[i]){
  740.       if(i<=32) framesize+=4; else framesize+=8;
  741.       if(stmw||(regnames[i][0]=='r'&®names[i][1]=='3'&®names[i][2]=='1'))
  742.         stmw=i;
  743.     }else{
  744.       if(stmw){ stme=stmw;stmw=0;}
  745.     }
  746.   }
  747.   if(!(g_flags[11]&USEDFLAG)) stme=0;
  748.   for(crsave=0,i=65;i<=72;i++)
  749.     if(regused[i]&&!regscratch[i]&&!regsa[i]) crsave=1;
  750.   if(crsave) framesize+=4;
  751.   if(framesize==8&&function_calls==0) framesize=frameoffset=0;
  752.   framesize=(framesize+15)/16*16;
  753.   if(function_calls)
  754.     fprintf(f,"\tmflr\t%s\n\tst%s\t%s,4(%s)\n",mregnames[t1],sdt[LONG],mregnames[t1],mregnames[sp]);
  755.   of=8+maxpushed+offset;
  756.   if(framesize!=0){
  757.     if(framesize<=32767){
  758.       fprintf(f,"\tstwu\t%s,-%ld(%s)\n",mregnames[sp],framesize,mregnames[sp]);
  759.       preg=sp;
  760.     }else{
  761.       fprintf(f,"\tmr\t%s,%s\n",mregnames[t2],mregnames[sp]);
  762.       fprintf(f,"\tlis\t%s,%ld\n",mregnames[t1],hi(-framesize));
  763.       fprintf(f,"\taddi\t%s,%s,%ld\n",mregnames[t1],mregnames[t1],lo(-framesize));
  764.       fprintf(f,"\tstwux\t%s,%s,%s\n",mregnames[sp],mregnames[sp],mregnames[t1]);
  765.       preg=t2;of-=framesize;
  766.     }
  767.   }
  768.   if(crsave){
  769.     fprintf(f,"\tmfcr\t%s\n\tst%s\t%s,%ld(%s)\n",mregnames[t1],sdt[LONG],mregnames[t1],of,mregnames[preg]);
  770.     of+=4;
  771.   }
  772.   for(i=1;i<=64;i++){
  773.     if(regused[i]&&!regscratch[i]&&!regsa[i]){
  774.       if(i<=32){
  775.         if(stme&&stme!=i&®names[i][1]=='3'&®names[i][2]=='1'){
  776.           fprintf(f,"\tstmw\t%s,%ld(%s)\n",mregnames[stme],of,mregnames[preg]);
  777.           of+=(stme-i+1)*4;
  778.           i=stme;
  779.         }else{
  780.           fprintf(f,"\tst%s\t%s,%ld(%s)\n",sdt[LONG],mregnames[i],of,mregnames[preg]);
  781.           of+=4;
  782.         }
  783.       }else{
  784.         fprintf(f,"\tst%s\t%s,%ld(%s)\n",sdt[DOUBLE],mregnames[i],of,mregnames[preg]);
  785.         of+=8;
  786.       }
  787.     }
  788.   }
  789. }
  790. static void function_bottom(FILE *f,struct Var *v,long offset)
  791. /*  Generates function bottom.                          */
  792. {
  793.   int i,preg;long of;
  794.   of=8+maxpushed+offset;
  795.   if(framesize<=32767){
  796.     preg=sp;
  797.   }else{
  798.     fprintf(f,"\tlwz\t%s,0(%s)\n",mregnames[t2],mregnames[sp]);
  799.     preg=t2;of-=framesize;
  800.   }
  801.   if(crsave){
  802.     fprintf(f,"\tl%s\t%s,%ld(%s)\n\tmtcr\t%s\n",ldt[LONG],mregnames[t1],of,mregnames[preg],mregnames[t1]);
  803.     of+=4;
  804.   }
  805.   for(i=1;i<=64;i++){
  806.     if(regused[i]&&!regscratch[i]&&!regsa[i]){
  807.       if(i<=32){
  808.         if(stme&&stme!=i&®names[i][1]=='3'&®names[i][2]=='1'){
  809.           fprintf(f,"\tlmw\t%s,%ld(%s)\n",mregnames[stme],of,mregnames[preg]);
  810.           of+=(stme-i+1)*4;
  811.           i=stme;
  812.         }else{
  813.           fprintf(f,"\tl%s\t%s,%ld(%s)\n",ldt[LONG],mregnames[i],of,mregnames[preg]);
  814.           of+=4;
  815.         }
  816.       }else{
  817.         fprintf(f,"\tl%s\t%s,%ld(%s)\n",ldt[DOUBLE],mregnames[i],of,mregnames[preg]);
  818.         of+=8;
  819.       }
  820.     }
  821.   }
  822.   if(framesize){
  823.     if(framesize<=32767)
  824.       fprintf(f,"\taddi\t%s,%s,%ld\n",mregnames[sp],mregnames[sp],framesize);
  825.     else
  826.       fprintf(f,"\tmr\t%s,%s\n",mregnames[sp],mregnames[preg]);
  827.   }
  828.   if(function_calls)
  829.     fprintf(f,"\tl%s\t%s,4(%s)\n\tmtlr\t%s\n",ldt[LONG],mregnames[t1],mregnames[sp],mregnames[t1]);
  830.   fprintf(f,"\tblr\n");
  831.   fprintf(f,"\t.type\t%s%s,@function\n",idprefix,v->identifier);
  832.   fprintf(f,"\t.size\t%s%s,$-%s%s\n",idprefix,v->identifier,idprefix,v->identifier);
  833. }
  834. static int is_const(struct Typ *t)
  835. /*  Tests if a type can be placed in the code-section.  */
  836. {
  837.     if(!(t->flags&(CONST|STRINGCONST))){
  838.         do{
  839.             if(t->flags&(CONST|STRINGCONST)) return(1);
  840.             if((t->flags&NQ)!=ARRAY) return(0);
  841.             t=t->next;
  842.         }while(1);
  843.     }else return(1);
  844. }
  845. static int balign(struct obj *o)
  846. /*  Liefert die unteren 2 Bits des Objekts. -1 wenn unklar. */
  847. {
  848.   int sc;
  849.   if(o->flags&DREFOBJ) return -1;
  850.   if(o->am) ierror(0);
  851.   if(!(o->flags&VAR)) ierror(0);
  852.   sc=o->v->storage_class;
  853.   if(sc==EXTERN||sc==STATIC){
  854.     /* Alle statischen Daten werden vom cg auf 32bit alignt. */
  855.     return zl2l(zland(o->val.vlong,l2zl(3L)));
  856.   }
  857.   if(sc==AUTO||sc==REGISTER){
  858.     zlong of=o->v->offset;
  859.     if(!zlleq(l2zl(0L),of))
  860.       of=zlsub(l2zl(0L),zladd(of,maxalign));
  861.     return zl2l(zland(zladd(of,o->val.vlong),l2zl(3L)));
  862.   }
  863.   ierror(0);
  864. }
  865.  
  866. /****************************************/
  867. /*  End of private data and functions.  */
  868. /****************************************/
  869.  
  870.  
  871. int init_cg(void)
  872. /*  Does necessary initializations for the code-generator. Gets called  */
  873. /*  once at the beginning and should return 0 in case of problems.      */
  874. {
  875.   int i;
  876.   /*  Initialize some values which cannot be statically initialized   */
  877.   /*  because they are stored in the target's arithmetic.             */
  878.   maxalign=l2zl(4L);
  879.   char_bit=l2zl(8L);
  880.   if(g_flags[7]&USEDFLAG){
  881.     malign[INT]=malign[LONG]=malign[POINTER]=malign[FLOAT]=malign[DOUBLE]=2;
  882.   }
  883.   for(i=0;i<16;i++){
  884.     sizetab[i]=l2zl(msizetab[i]);
  885.     align[i]=l2zl(malign[i]);
  886.   }
  887.   for(i=0;i<=MAXR;i++) mregnames[i]=regnames[i];
  888.   for(i= 1;i<=32;i++){
  889.     regsize[i]=l2zl(4L);
  890.     regtype[i]=<yp;
  891.     if(g_flags[8]&USEDFLAG) mregnames[i]++;
  892.   }
  893.   for(i=33;i<=64;i++){
  894.     regsize[i]=l2zl(8L);
  895.     regtype[i]=&ldbl;
  896.     if(g_flags[8]&USEDFLAG) mregnames[i]++;
  897.   }
  898.   for(i=65;i<=72;i++){
  899.     regsize[i]=l2zl(1L);
  900.     regtype[i]=&lchar;
  901.     if(g_flags[8]&USEDFLAG) mregnames[i]+=2;
  902.   }
  903.  
  904.   /*  Use multiple ccs.   */
  905.   multiple_ccs=1;
  906.  
  907.   /*  Initialize the min/max-settings. Note that the types of the     */
  908.   /*  host system may be different from the target system and you may */
  909.   /*  only use the smallest maximum values ANSI guarantees if you     */
  910.   /*  want to be portable.                                            */
  911.   /*  That's the reason for the subtraction in t_min[INT]. Long could */
  912.   /*  be unable to represent -2147483648 on the host system.          */
  913.   t_min[UNSIGNED|CHAR]=t_min[UNSIGNED|SHORT]=t_min[UNSIGNED|INT]=t_min[UNSIGNED|LONG]=l2zl(0L);
  914.   t_min[CHAR]=l2zl(-128L);
  915.   t_min[SHORT]=l2zl(-32768L);
  916.   t_min[INT]=zlsub(l2zl(-2147483647L),l2zl(1L));
  917.   t_min[LONG]=t_min[INT];
  918.   t_max[CHAR]=ul2zul(127UL);
  919.   t_max[SHORT]=ul2zul(32767UL);
  920.   t_max[INT]=ul2zul(2147483647UL);
  921.   t_max[LONG]=t_max[INT];
  922.   t_max[UNSIGNED|CHAR]=ul2zul(255UL);
  923.   t_max[UNSIGNED|SHORT]=ul2zul(65535UL);
  924.   t_max[UNSIGNED|INT]=ul2zul(4294967295UL);
  925.   t_max[UNSIGNED|LONG]=t_max[UNSIGNED|INT];
  926.   /*  Reserve a few registers for use by the code-generator.      */
  927.   /*  This is not optimal but simple.                             */
  928.   regsa[t1]=regsa[t2]=regsa[t3]=1;
  929.   regsa[f1]=regsa[f2]=regsa[f3]=1;
  930.   regsa[sp]=regsa[fp]=regsa[sd]=regsa[r2]=1;
  931.   regscratch[t1]=regscratch[t2]=regscratch[t3]=0;
  932.   regscratch[f1]=regscratch[f2]=regscratch[f3]=0;
  933.   regscratch[sp]=regscratch[fp]=regscratch[sd]=regscratch[r2]=0;
  934.  
  935.   if(g_flags[6]&USEDFLAG) {labprefix=".l";idprefix="";}
  936.  
  937.   return(1);
  938. }
  939.  
  940. int freturn(struct Typ *t)
  941. /*  Returns the register in which variables of type t are returned. */
  942. /*  If the value cannot be returned in a register returns 0.        */
  943. /*  A pointer MUST be returned in a register. The code-generator    */
  944. /*  has to simulate a pseudo register if necessary.                 */
  945. {
  946.     if((t->flags&NQ)==FLOAT||(t->flags&NQ)==DOUBLE) return(46);
  947.     if((t->flags&NQ)==STRUCT||(t->flags&NQ)==UNION) return(0);
  948.     if(zlleq(szof(t),l2zl(4L))) return(r3); else return(0);
  949. }
  950.  
  951. int regok(int r,int t,int mode)
  952. /*  Returns 0 if register r cannot store variables of   */
  953. /*  type t. If t==POINTER and mode!=0 then it returns   */
  954. /*  non-zero only if the register can store a pointer   */
  955. /*  and dereference a pointer to mode.                  */
  956. {
  957.     if(r==0) return(0);
  958.     t&=NQ;
  959.     if(t==0){
  960.         if(r>=65&&r<=72) return(1); else return(0);
  961.     }
  962.     if((t==FLOAT||t==DOUBLE)&&r>=33&&r<=64) return(1);
  963.     if(t==POINTER&&r>=1&&r<=32) return(1);
  964.     if(t>=CHAR&&t<=LONG&&r>=1&&r<=32) return(1);
  965.     return(0);
  966. }
  967.  
  968. int dangerous_IC(struct IC *p)
  969. /*  Returns zero if the IC p can be safely executed     */
  970. /*  without danger of exceptions or similar things.     */
  971. /*  vbcc may generate code in which non-dangerous ICs   */
  972. /*  are sometimes executed although control-flow may    */
  973. /*  never reach them (mainly when moving computations   */
  974. /*  out of loops).                                      */
  975. /*  Typical ICs that generate exceptions on some        */
  976. /*  machines are:                                       */
  977. /*      - accesses via pointers                         */
  978. /*      - division/modulo                               */
  979. /*      - overflow on signed integer/floats             */
  980. {
  981.     int c=p->code;
  982.     if((p->q1.flags&DREFOBJ)||(p->q2.flags&DREFOBJ)||(p->z.flags&DREFOBJ))
  983.         return(0);
  984.     if((c==DIV||c==MOD)&&!(p->q2.flags&KONST))
  985.         return(1);
  986.     return(0);
  987. }
  988.  
  989. int must_convert(np p,int t)
  990. /*  Returns zero if code for converting np to type t    */
  991. /*  can be omitted.                                     */
  992. /*  On the PowerPC cpu pointers and 32bit               */
  993. /*  integers have the same representation and can use   */
  994. /*  the same registers.                                 */
  995. {
  996.     int o=p->ntyp->flags,op=o&NQ,tp=t&NQ;
  997.     if((op==INT||op==LONG||op==POINTER)&&(tp==INT||tp==LONG||tp==POINTER))
  998.       return(0);
  999.     return(1);
  1000. }
  1001.  
  1002. void gen_ds(FILE *f,zlong size,struct Typ *t)
  1003. /*  This function has to create <size> bytes of storage */
  1004. /*  initialized with zero.                              */
  1005. {
  1006.     if(newobj) fprintf(f,"%ld\n",zl2l(size));
  1007.         else   fprintf(f,"\t.space\t%ld\n",zl2l(size));
  1008.     newobj=0;
  1009. }
  1010.  
  1011. void gen_align(FILE *f,zlong align)
  1012. /*  This function has to make sure the next data is     */
  1013. /*  aligned to multiples of <align> bytes.              */
  1014. {
  1015.     fprintf(f,"\t.align\t2\n");
  1016. }
  1017.  
  1018. void gen_var_head(FILE *f,struct Var *v)
  1019. /*  This function has to create the head of a variable  */
  1020. /*  definition, i.e. the label and information for      */
  1021. /*  linkage etc.                                        */
  1022. {
  1023.     int constflag;
  1024.     if(v->clist) constflag=is_const(v->vtyp);
  1025.     if(v->storage_class==STATIC){
  1026.         if((v->vtyp->flags&NQ)==FUNKT) return;
  1027.         if(v->clist&&(!constflag||(g_flags[2]&USEDFLAG))&§ion!=DATA){fprintf(f,dataname);section=DATA;}
  1028.         if(v->clist&&constflag&&!(g_flags[2]&USEDFLAG)&§ion!=RODATA){fprintf(f,rodataname);section=RODATA;}
  1029.         if(!v->clist&§ion!=BSS){fprintf(f,bssname);section=BSS;}
  1030.         fprintf(f,"\t.type\t%s%ld,@object\n",labprefix,zl2l(v->offset));
  1031.         fprintf(f,"\t.size\t%s%ld,%ld\n",labprefix,zl2l(v->offset),zl2l(szof(v->vtyp)));
  1032.         if(section!=BSS) fprintf(f,"%s%ld:\n",labprefix,zl2l(v->offset));
  1033.             else fprintf(f,"\t.lcomm\t%s%ld,",labprefix,zl2l(v->offset));
  1034.         newobj=1;
  1035.     }
  1036.     if(v->storage_class==EXTERN){
  1037.         fprintf(f,"\t.global\t%s%s\n",idprefix,v->identifier);
  1038.         if(v->flags&(DEFINED|TENTATIVE)){
  1039.             if(v->clist&&(!constflag||(g_flags[2]&USEDFLAG))&§ion!=DATA){fprintf(f,dataname);section=DATA;}
  1040.             if(v->clist&&constflag&&!(g_flags[2]&USEDFLAG)&§ion!=RODATA){fprintf(f,rodataname);section=RODATA;}
  1041.             if(!v->clist&§ion!=BSS){fprintf(f,bssname);section=BSS;}
  1042.             fprintf(f,"\t.type\t%s%s,@object\n",idprefix,v->identifier);
  1043.             fprintf(f,"\t.size\t%s%s,%ld\n",idprefix,v->identifier,zl2l(szof(v->vtyp)));
  1044.             if(section!=BSS) fprintf(f,"%s%s:\n",idprefix,v->identifier);
  1045.                 else fprintf(f,"\t.comm\t%s%s,",idprefix,v->identifier);
  1046.             newobj=1;
  1047.         }
  1048.     }
  1049. }
  1050.  
  1051. void gen_dc(FILE *f,int t,struct const_list *p)
  1052. /*  This function has to create static storage          */
  1053. /*  initialized with const-list p.                      */
  1054. {
  1055.     if((t&NQ)==POINTER) t=UNSIGNED|LONG;
  1056.     fprintf(f,"\t.%s\t",dct[t&NQ]);
  1057.     if(!p->tree){
  1058.         if((t&NQ)==FLOAT||(t&NQ)==DOUBLE){
  1059.         /*  auch wieder nicht sehr schoen und IEEE noetig   */
  1060.             unsigned char *ip;
  1061.             ip=(unsigned char *)&p->val.vdouble;
  1062.             fprintf(f,"0x%02x%02x%02x%02x",ip[0],ip[1],ip[2],ip[3]);
  1063.             if((t&NQ)==DOUBLE){
  1064.                 fprintf(f,",0x%02x%02x%02x%02x",ip[4],ip[5],ip[6],ip[7]);
  1065.             }
  1066.         }else{
  1067.             printval(f,&p->val,t&NU,0);
  1068.         }
  1069.     }else{
  1070.         probj2(f,&p->tree->o,t&NU);
  1071.     }
  1072.     fprintf(f,"\n");newobj=0;
  1073. }
  1074.  
  1075.  
  1076. /*  The main code-generation routine.                   */
  1077. /*  f is the stream the code should be written to.      */
  1078. /*  p is a pointer to a doubly linked list of ICs       */
  1079. /*  containing the function body to generate code for.  */
  1080. /*  v is a pointer to the function.                     */
  1081. /*  offset is the size of the stackframe the function   */
  1082. /*  needs for local variables.                          */
  1083.  
  1084. void gen_code(FILE *f,struct IC *p,struct Var *v,zlong offset)
  1085. /*  The main code-generation.                                           */
  1086. {
  1087.   int c,t,i,addbuf,varargs=0,fixedgpr,fixedfpr,setcc,ccset;
  1088.   char *fpp;int fpf;struct IC *m;
  1089.   long of=(zl2l(offset)+3)/4*4,regbase,tmpoff;
  1090.   if(DEBUG&1) printf("gen_code()\n");
  1091.   for(c=1;c<=MAXR;c++) regs[c]=regsa[c];
  1092.   maxpushed=0;addbuf=0;
  1093.   for(m=p;m;m=m->next){
  1094.     c=m->code;t=m->typf&NU;
  1095.     if(c==ALLOCREG) {regs[m->q1.reg]=1;continue;}
  1096.     if(c==FREEREG) {regs[m->q1.reg]=0;continue;}
  1097.     if(c==COMPARE&&(m->q2.flags&KONST)){
  1098.       eval_const(&m->q2.val,t);
  1099.       if(zleqto(vlong,l2zl(0L))&&zdeqto(vdouble,d2zd(0.0))){
  1100.         m->q2.flags=0;m->code=c=TEST;
  1101.       }
  1102.     }
  1103.     if((t&NQ)<=LONG&&(m->q2.flags&KONST)&&(t&NQ)<=LONG&&(c==MULT||c==DIV||(c==MOD&&(t&UNSIGNED)))){
  1104.       eval_const(&m->q2.val,t);
  1105.       i=pof2(vlong);
  1106.       if(i){
  1107.         if(c==MOD){
  1108.           vlong=zlsub(vlong,l2zl(1L));
  1109.           m->code=AND;
  1110.         }else{
  1111.           vlong=l2zl(i-1);
  1112.           if(c==DIV) m->code=RSHIFT; else m->code=LSHIFT;
  1113.         }
  1114.         c=m->code;
  1115.         if((t&NU)==CHAR) m->q2.val.vchar=zl2zc(vlong);
  1116.         else if((t&NU)==SHORT) m->q2.val.vshort=zl2zs(vlong);
  1117.         else if((t&NU)==INT) m->q2.val.vint=zl2zi(vlong);
  1118.         else if((t&NU)==LONG) m->q2.val.vlong=vlong;
  1119.         vulong=zl2zul(vlong);
  1120.         if((t&NU)==(UNSIGNED|CHAR)) m->q2.val.vuchar=zul2zuc(vulong);
  1121.         else if((t&NU)==(UNSIGNED|SHORT)) m->q2.val.vushort=zul2zus(vulong);
  1122.         else if((t&NU)==(UNSIGNED|INT))  m->q2.val.vuint=zul2zui(vulong);
  1123.         else if((t&NU)==(UNSIGNED|LONG)) m->q2.val.vulong=vulong;
  1124.       }
  1125.     }
  1126.     if((c==CONVFLOAT||c==CONVDOUBLE)&&t!=FLOAT&&t!=DOUBLE&&addbuf<8) addbuf=8;
  1127.     if((t==FLOAT||t==DOUBLE)&&c>=CONVCHAR&&c<=CONVULONG&&addbuf<8) addbuf=8;
  1128.     if(c==CALL&&maxpushed<zl2l(m->q2.val.vlong)) maxpushed=zl2l(m->q2.val.vlong);
  1129.     if(c==CALL&&(m->q1.flags&VAR)&&!strcmp(m->q1.v->identifier,"__va_start")) varargs=1;
  1130.   }
  1131.   if(g_flags[9]&USEDFLAG) peephole(p);
  1132.   if(varargs){
  1133.     fixedgpr=fixedfpr=0;
  1134.     for(i=0;i<v->vtyp->exact->count;i++){
  1135.       c=(*v->vtyp->exact->sl)[i].styp->flags&NQ;
  1136.       if(c==POINTER||c<=LONG) fixedgpr++;
  1137.       if(c==FLOAT||c==DOUBLE) fixedfpr++;
  1138.     }
  1139.     regbase=of; /* merken */
  1140.     addbuf+=96;
  1141.   }
  1142.   of+=addbuf;tmpoff=8+maxpushed+of;
  1143.   function_top(f,v,of);
  1144.   if(varargs){
  1145.     regbase=frameoffset+regbase;
  1146.     fpp="";
  1147.     if(!(g_flags[8]&USEDFLAG)) fpp="r";
  1148.     for(i=fixedgpr;i<8;i++)
  1149.       fprintf(f,"\tstw\t%s%d,%ld(%s)\n",fpp,i+3,regbase+i*4,mregnames[sp]);
  1150.     if(!(g_flags[8]&USEDFLAG)) fpp="f";
  1151.     for(i=fixedfpr;i<8;i++)
  1152.       fprintf(f,"\tstfd\t%s%d,%ld(%s)\n",fpp,i+1,regbase+32+i*8,mregnames[sp]);
  1153.   }
  1154.   pushed=0;ccset=0;
  1155.   for(;p;pr(f,p),p=p->next){
  1156.     c=p->code;t=p->typf;
  1157.     if(c<0) {setcc=1;c=-c;} else setcc=0;
  1158.     if(c==NOP) {p->z.flags=0;continue;}
  1159.     if(c==ALLOCREG) {regs[p->q1.reg]=1;continue;}
  1160.     if(c==FREEREG) {regs[p->q1.reg]=0;continue;}
  1161.     if(c==LABEL) {ccset=0;fprintf(f,"%s%d:\n",labprefix,t);continue;}
  1162.     if(c==BRA) {ccset=0;fprintf(f,"\tb\t%s%d\n",labprefix,t);continue;}
  1163.     if(c>=BEQ&&c<BRA){
  1164.       ccset=0;
  1165.       if(!(p->q1.flags®)) p->q1.reg=cr0;
  1166.       if((g_flags[9]&USEDFLAG)&&!BTST(twice,p->typf-lastlabel)){
  1167.         struct IC *p2,*p3,*p4;int exit_label;
  1168.         p2=p->next;
  1169.         while(p2&&(p2->code==FREEREG||p2->code==ALLOCREG)) p2=p2->next;
  1170.         if(p2&&p2->code==SETRETURN&&p2->z.reg){p2->code=ASSIGN;p2->z.flags=REG;}
  1171.         if(p2&&p2->code==ASSIGN&&(p2->z.flags&(REG|DREFOBJ))==REG&&p2->z.reg<=32){
  1172.           p3=p2->next;
  1173.           while(p3&&(p3->code==FREEREG||p3->code==ALLOCREG)) p3=p3->next;
  1174.           if(p3&&p3->code==BRA){
  1175.             exit_label=p3->typf;
  1176.             p3=p3->next;
  1177.             while(p3&&(p3->code==FREEREG||p3->code==ALLOCREG)) p3=p3->next;
  1178.             if(p3&&p3->code==LABEL&&p3->typf==p->typf){
  1179.               p3=p3->next;
  1180.               while(p3&&(p3->code==FREEREG||p3->code==ALLOCREG)) p3=p3->next;
  1181.               if(p3&&p3->code==SETRETURN&&p3->z.reg){p3->code=ASSIGN;p3->z.flags=REG;}
  1182.               if(p3&&p3->code==ASSIGN&&(p3->z.flags&(REG|DREFOBJ))==REG&&p3->z.reg==p2->z.reg){
  1183.                 p4=p3->next;
  1184.                 while(p4&&(p4->code==FREEREG||p4->code==ALLOCREG)) p4=p4->next;
  1185.                 if(p4&&p4->code==LABEL&&p4->typf==exit_label){
  1186.                   int bit=(p->q1.reg-cr0)*4;
  1187.                   if((p2->q1.flags&KONST)&&(p3->q1.flags&KONST)){
  1188.                     eval_const(&p2->q1.val,p2->typf);
  1189.                     if(zleqto(vlong,l2zl(0L))){
  1190.                       eval_const(&p3->q1.val,p3->typf);
  1191.                       if(zleqto(vlong,l2zl(1L))||zleqto(vlong,l2zl(-1L))){
  1192.                         if(c==BLE){fprintf(f,"\tcror\t%d,%d,%d\n",bit,bit,bit+2);}
  1193.                         if(c==BGE){bit++;fprintf(f,"\tcror\t%d,%d,%d\n",bit,bit,bit+1);}
  1194.                         if(c==BNE){bit+=2;fprintf(f,"\tcrnor\t%d,%d,%d\n",bit,bit,bit);}
  1195.                         if(c==BGT) bit++;
  1196.                         if(c==BEQ) bit+=2;
  1197.                         fprintf(f,"\tmfcr\t%s\n",mregnames[t1]);
  1198.                         fprintf(f,"\trlwinm\t%s,%s,%d,%d,%d\n",mregnames[p2->z.reg],mregnames[t1],bit+1,31,31);
  1199.                         if(zleqto(vlong,l2zl(-1L))) fprintf(f,"\tneg\t%s,%s\n",mregnames[p2->z.reg],mregnames[p2->z.reg]);
  1200.                         if(BTST(twice,p4->typf-lastlabel)) fprintf(f,"%s%d:\n",labprefix,p4->typf);
  1201.                         p=p4;continue;
  1202.                       }
  1203.                     }else{
  1204.                       eval_const(&p3->q1.val,p3->typf);
  1205.                       if(zleqto(vlong,l2zl(0L))){
  1206.                         eval_const(&p2->q1.val,p2->typf);
  1207.                         if(zleqto(vlong,l2zl(1L))||zleqto(vlong,l2zl(-1L))){
  1208.                           if(c==BLE){fprintf(f,"\tcrnor\t%d,%d,%d\n",bit,bit,bit+2);}
  1209.                           if(c==BGE){bit++;fprintf(f,"\tcrnor\t%d,%d,%d\n",bit,bit,bit+1);}
  1210.                           if(c==BNE){bit+=2;}
  1211.                           if(c==BGT){bit++;fprintf(f,"\tcrnor\t%d,%d,%d\n",bit,bit,bit);}
  1212.                           if(c==BEQ){bit+=2;fprintf(f,"\tcrnor\t%d,%d,%d\n",bit,bit,bit);}
  1213.                           if(c==BLT){fprintf(f,"\tcrnor\t%d,%d,%d\n",bit,bit,bit);}
  1214.                           fprintf(f,"\tmfcr\t%s\n",mregnames[t1]);
  1215.                           fprintf(f,"\trlwinm\t%s,%s,%d,%d,%d\n",mregnames[p2->z.reg],mregnames[t1],bit+1,31,31);
  1216.                           if(zleqto(vlong,l2zl(-1L))) fprintf(f,"\tneg\t%s,%s\n",mregnames[p2->z.reg],mregnames[p2->z.reg]);
  1217.                           if(BTST(twice,p4->typf-lastlabel)) fprintf(f,"%s%d:\n",labprefix,p4->typf);
  1218.                           p=p4;continue;
  1219.                         }
  1220.                       }
  1221.                     }
  1222.                   }
  1223.                 }
  1224.               }
  1225.             }
  1226.           }
  1227.         }
  1228.       }
  1229.       fprintf(f,"\tb%s\t%s,%s%d\n",ccs[c-BEQ],mregnames[p->q1.reg],labprefix,t);
  1230.       continue;
  1231.     }
  1232.     if(c==MOVETOREG){
  1233.       if(p->z.reg<=32){
  1234.         load_reg(f,p->z.reg,&p->q1,INT,0);
  1235.       }else{
  1236.         if(p->z.reg>64) ierror(0);
  1237.         load_reg(f,p->z.reg,&p->q1,DOUBLE,0);
  1238.       }
  1239.       p->z.flags=0;
  1240.       continue;
  1241.     }
  1242.     if(c==MOVEFROMREG){
  1243.       if(p->q1.reg<=32){
  1244.         store_reg(f,p->q1.reg,&p->z,INT);
  1245.       }else{
  1246.         if(p->q1.reg>64) ierror(0);
  1247.         store_reg(f,p->q1.reg,&p->z,DOUBLE);
  1248.       }
  1249.       p->z.flags=0;
  1250.       continue;
  1251.     }
  1252.     if((c==ASSIGN||c==PUSH)&&((t&NQ)>POINTER||((t&NQ)==CHAR&&zl2l(p->q2.val.vlong)!=1))){
  1253.       unsigned long size,l;
  1254.       int a1,a2,b;char *ld,*st;
  1255.       size=zl2l(p->q2.val.vlong);
  1256.       a1=balign(&p->q1);
  1257.       if(c==ASSIGN) a2=balign(&p->z); else a2=0;
  1258.       b=1;ld=ldt[CHAR];st=sdt[CHAR];
  1259.       if(a1>=0&&a2>=0){
  1260.         if(a1==0&&a2==0){
  1261.           b=4;ld=ldt[INT];st=sdt[INT];
  1262.         }else if((a1&1)==0&&(a2&1)==0){
  1263.           b=2;ld=ldt[SHORT];st=sdt[SHORT];
  1264.         }
  1265.       }
  1266.       if(p->q1.flags&DREFOBJ){
  1267.         p->q1.flags&=~DREFOBJ;
  1268.         load_reg(f,t1,&p->q1,POINTER,t1);
  1269.         p->q1.flags|=DREFOBJ;
  1270.       }else{
  1271.         load_address(f,t1,&p->q1,POINTER);
  1272.       }
  1273.       if(p->z.flags&DREFOBJ){
  1274.         p->z.flags&=~DREFOBJ;
  1275.         load_reg(f,t2,&p->z,POINTER,t2);
  1276.         p->z.flags|=DREFOBJ;
  1277.       }else{
  1278.         if(c==PUSH){
  1279.           if(!(p->q1.flags&VAR)) ierror(0);
  1280.           if(zl2l(falign(p->q1.v->vtyp))==8) pushed=(pushed+7)/8*8;
  1281.           fprintf(f,"\taddi\t%s,%s,%ld\n",mregnames[t2],mregnames[sp],pushed+8-b);
  1282.           pushed+=size;
  1283.         }else{
  1284.           load_address(f,t2,&p->z,POINTER);
  1285.         }
  1286.       }
  1287.       fprintf(f,"\taddi\t%s,%s,-%d\n",mregnames[t1],mregnames[t1],b);
  1288.       if(c==ASSIGN) fprintf(f,"\taddi\t%s,%s,-%d\n",mregnames[t2],mregnames[t2],b);
  1289.       l=size/(8*b);
  1290.       if(l>1){
  1291.         if(hi(l)) fprintf(f,"\tlis\t%s,%ld\n",mregnames[t3],hi(l));
  1292.         fprintf(f,"\tli\t%s,%ld\n",mregnames[t3],lo(l));
  1293.         fprintf(f,"\tmtctr\t%s\n",mregnames[t3]);
  1294.         fprintf(f,"%s%d:\n",labprefix,++label);
  1295.       }
  1296.       if(l>0){
  1297.         for(i=b;i<=7*b;i+=b){
  1298.           fprintf(f,"\tl%s\t%s,%d(%s)\n",ld,mregnames[t3],i,mregnames[t1]);
  1299.           fprintf(f,"\tst%s\t%s,%d(%s)\n",st,mregnames[t3],i,mregnames[t2]);
  1300.         }
  1301.         fprintf(f,"\tl%su\t%s,%d(%s)\n",ld,mregnames[t3],i,mregnames[t1]);
  1302.         fprintf(f,"\tst%su\t%s,%d(%s)\n",st,mregnames[t3],i,mregnames[t2]);
  1303.       }
  1304.       if(l>1){
  1305.         fprintf(f,"\tbdnz\t%s%d\n",labprefix,label);
  1306.       }
  1307.       size=size%(8*b);
  1308.       for(i=0;i<size/b;i++){
  1309.         fprintf(f,"\tl%su\t%s,%d(%s)\n",ld,mregnames[t3],b,mregnames[t1]);
  1310.         fprintf(f,"\tst%su\t%s,%d(%s)\n",st,mregnames[t3],b,mregnames[t2]);
  1311.       }
  1312.       size=size%b;i=b;
  1313.       if(size&2){
  1314.         fprintf(f,"\tl%su\t%s,%d(%s)\n",ldt[SHORT],mregnames[t3],b,mregnames[t1]);
  1315.         fprintf(f,"\tst%su\t%s,%d(%s)\n",sdt[SHORT],mregnames[t3],b,mregnames[t2]);
  1316.         i=2;
  1317.       }
  1318.       if(size&1){
  1319.         fprintf(f,"\tl%su\t%s,%d(%s)\n",ldt[CHAR],mregnames[t3],i,mregnames[t1]);
  1320.         fprintf(f,"\tst%su\t%s,%d(%s)\n",sdt[CHAR],mregnames[t3],i,mregnames[t2]);
  1321.       }
  1322.       p->z.flags=0;
  1323.       continue;
  1324.     }
  1325.     if(!ccset&&c==TEST&&((t&NQ)==FLOAT||(t&NQ)==DOUBLE)){
  1326.       p->code=c=COMPARE;
  1327.       p->q2.flags=KONST;
  1328.       p->q2.val.vdouble=d2zd(0.0);
  1329.       if((t&NQ)==FLOAT) p->q2.val.vfloat=zd2zf(p->q2.val.vdouble);
  1330.     }
  1331.     p=do_refs(f,p);
  1332.     c=p->code;
  1333.     if(c<0) {setcc=1;c=-c;} else setcc=0;
  1334.     if(c==SUBPFP) c=SUB;
  1335.     if(c==ADDI2P) c=ADD;
  1336.     if(c==SUBIFP) c=SUB;
  1337.     if(c>=CONVCHAR&&c<=CONVULONG){
  1338.       int to;
  1339.       static struct obj o;char *ip;
  1340.       if(c==CONVCHAR) to=CHAR;
  1341.       if(c==CONVUCHAR) to=UNSIGNED|CHAR;
  1342.       if(c==CONVSHORT) to=SHORT;
  1343.       if(c==CONVUSHORT) to=UNSIGNED|SHORT;
  1344.       if(c==CONVINT) to=LONG;
  1345.       if(c==CONVUINT) to=UNSIGNED|LONG;
  1346.       if(c==CONVLONG) to=LONG;
  1347.       if(c==CONVULONG) to=UNSIGNED|LONG;
  1348.       if(c==CONVFLOAT) to=FLOAT;
  1349.       if(c==CONVDOUBLE) to=DOUBLE;
  1350.       if(c==CONVPOINTER) to=UNSIGNED|LONG;
  1351.       if(to==FLOAT||to==DOUBLE){
  1352.         if((t&NQ)==FLOAT||(t&NQ)==DOUBLE){
  1353.           zreg=q1reg;
  1354.           continue;
  1355.         }
  1356.         if((t&NU)==(UNSIGNED|INT)||(t&NU)==(UNSIGNED|LONG)){
  1357.           o.flags=KONST;
  1358.           ip=(char *)&o.val.vdouble;
  1359.           ip[0]=0x41;
  1360.           ip[1]=0xe0;
  1361.           ip[2]=0x00;
  1362.           ip[3]=0x00;
  1363.           ip[4]=0x00;
  1364.           ip[5]=0x00;
  1365.           ip[6]=0x00;
  1366.           ip[7]=0x00;
  1367.           load_reg(f,f2,&o,DOUBLE,t2);
  1368.           fprintf(f,"\tfcmpu\t%s,%s,%s\n",mregnames[cr0],mregnames[q1reg],mregnames[f2]);
  1369.           fprintf(f,"\tcror\t3,2,1\n");
  1370.           fprintf(f,"\tbso\t%s,%s%d\n",mregnames[cr0],labprefix,++label);
  1371.           fprintf(f,"\tfctiwz\t%s,%s\n",mregnames[f2],mregnames[q1reg]);
  1372.           fprintf(f,"\tst%s\t%s,%ld(%s)\n",sdt[DOUBLE],mregnames[f2],tmpoff-8,mregnames[sp]);
  1373.           fprintf(f,"\tl%s\t%s,%ld(%s)\n",ldt[t&NQ],mregnames[zreg],tmpoff-zl2l(sizetab[t&NQ]),mregnames[sp]);
  1374.           fprintf(f,"\tb\t%s%d\n",labprefix,++label);
  1375.           fprintf(f,"%s%d:\n",labprefix,label-1);
  1376.           fprintf(f,"\tfsub\t%s,%s,%s\n",mregnames[f2],mregnames[q1reg],mregnames[f2]);
  1377.           fprintf(f,"\tfctiwz\t%s,%s\n",mregnames[f2],mregnames[f2]);
  1378.           fprintf(f,"\tst%s\t%s,%ld(%s)\n",sdt[DOUBLE],mregnames[f2],tmpoff-8,mregnames[sp]);
  1379.           fprintf(f,"\tl%s\t%s,%ld(%s)\n",ldt[INT],mregnames[zreg],tmpoff-zl2l(sizetab[t&NQ]),mregnames[sp]);
  1380.           fprintf(f,"\txoris\t%s,%s,32768\n",mregnames[zreg],mregnames[zreg]);
  1381.           fprintf(f,"%s%d:\n",labprefix,label);
  1382.         }else{
  1383.           fprintf(f,"\tfctiwz\t%s,%s\n",mregnames[f3],mregnames[q1reg]);
  1384.           fprintf(f,"\tst%s\t%s,%ld(%s)\n",sdt[DOUBLE],mregnames[f3],tmpoff-8,mregnames[sp]);
  1385.           fprintf(f,"\tl%s\t%s,%ld(%s)\n",ldt[t&NQ],mregnames[zreg],tmpoff-zl2l(sizetab[t&NQ]),mregnames[sp]);
  1386.         }
  1387.         if(t==CHAR) fprintf(f,"\textsb\t%s,%s\n",mregnames[zreg],mregnames[zreg]);
  1388.         continue;
  1389.       }
  1390.       if((t&NQ)==FLOAT||(t&NQ)==DOUBLE){
  1391.         o.flags=KONST;
  1392.         ip=(char *)&o.val.vdouble;
  1393.         ip[0]=0x43;
  1394.         ip[1]=0x30;
  1395.         ip[2]=0x00;
  1396.         ip[3]=0x00;
  1397.         ip[4]=0x80;
  1398.         ip[5]=0x00;
  1399.         ip[6]=0x00;
  1400.         ip[7]=0x00;
  1401.         if((to&NU)==(UNSIGNED|INT)||(to&NU)==(UNSIGNED|LONG)){
  1402.           ip[4]=0x00;
  1403.           load_reg(f,f2,&o,DOUBLE,t2);
  1404.           fprintf(f,"\tlis\t%s,17200\n",mregnames[t2]);
  1405.           fprintf(f,"\tst%s\t%s,%ld(%s)\n",sdt[INT],mregnames[q1reg],tmpoff-4,mregnames[sp]);
  1406.           fprintf(f,"\tst%s\t%s,%ld(%s)\n",sdt[INT],mregnames[t2],tmpoff-8,mregnames[sp]);
  1407.           fprintf(f,"\tl%s\t%s,%ld(%s)\n",ldt[DOUBLE],mregnames[zreg],tmpoff-8,mregnames[sp]);
  1408.           fprintf(f,"\tfsub\t%s,%s,%s\n",mregnames[zreg],mregnames[zreg],mregnames[f2]);
  1409.         }else{
  1410.           fprintf(f,"\tlis\t%s,17200\n",mregnames[t2]);
  1411.           fprintf(f,"\tst%s\t%s,%ld(%s)\n",sdt[INT],mregnames[t2],tmpoff-8,mregnames[sp]);
  1412.           fprintf(f,"\txoris\t%s,%s,32768\n",mregnames[t2],mregnames[q1reg]);
  1413.           fprintf(f,"\tst%s\t%s,%ld(%s)\n",sdt[INT],mregnames[t2],tmpoff-4,mregnames[sp]);
  1414.           fprintf(f,"\tl%s\t%s,%ld(%s)\n",ldt[DOUBLE],mregnames[zreg],tmpoff-8,mregnames[sp]);
  1415.           load_reg(f,f2,&o,DOUBLE,t2);
  1416.           fprintf(f,"\tfsub\t%s,%s,%s\n",mregnames[zreg],mregnames[zreg],mregnames[f2]);
  1417.         }
  1418.         continue;
  1419.       }
  1420.       if((t&NQ)>=(to&NQ)){
  1421.         if((t&UNSIGNED)==(to&UNSIGNED)){
  1422.           if(setcc){
  1423.             fprintf(f,"\tmr.\t%s,%s\n",mregnames[zreg],mregnames[q1reg]);
  1424.             ccset=1;
  1425.           }else{
  1426.             zreg=q1reg;
  1427.           }
  1428.           continue;
  1429.         }else{
  1430.           if((t&NU)==CHAR){
  1431.             fprintf(f,"\textsb%s\t%s,%s\n",record[setcc],mregnames[zreg],mregnames[q1reg]);
  1432.             ccset|=setcc;
  1433.           }else if((t&NU)==SHORT){
  1434.             fprintf(f,"\textsh%s\t%s,%s\n",record[setcc],mregnames[zreg],mregnames[q1reg]);
  1435.             ccset|=setcc;
  1436.           }else if((t&NU)==(UNSIGNED|CHAR)){
  1437.             fprintf(f,"\tandi.\t%s,%s,255\n",mregnames[zreg],mregnames[q1reg]);
  1438.             ccset=setcc;
  1439.           }else if((t&NU)==(UNSIGNED|SHORT)){
  1440.             fprintf(f,"\tandi.\t%s,%s,65535\n",mregnames[zreg],mregnames[q1reg]);
  1441.             ccset=setcc;
  1442.           }else{
  1443.             if(setcc){
  1444.               fprintf(f,"\tmr.\t%s,%s\n",mregnames[zreg],mregnames[q1reg]);
  1445.               ccset=1;
  1446.             }else{
  1447.               zreg=q1reg;
  1448.             }
  1449.           }
  1450.           continue;
  1451.         }
  1452.       }else{
  1453.         if((t&NU)==CHAR){
  1454.           fprintf(f,"\textsb%s\t%s,%s\n",record[setcc],mregnames[zreg],mregnames[q1reg]);
  1455.           ccset|=setcc;
  1456.         }else if((t&NU)==SHORT){
  1457.           fprintf(f,"\textsh%s\t%s,%s\n",record[setcc],mregnames[zreg],mregnames[q1reg]);
  1458.           ccset|=setcc;
  1459.         }else if((t&NU)==(UNSIGNED|CHAR)){
  1460.           fprintf(f,"\tandi.\t%s,%s,255\n",mregnames[zreg],mregnames[q1reg]);
  1461.           ccset=setcc;
  1462.         }else if((t&NU)==(UNSIGNED|SHORT)){
  1463.           fprintf(f,"\tandi.\t%s,%s,65535\n",mregnames[zreg],mregnames[q1reg]);
  1464.           ccset=setcc;
  1465.         }else{
  1466.           if(setcc){
  1467.             fprintf(f,"\tmr.\t%s,%s\n",mregnames[zreg],mregnames[q1reg]);
  1468.             ccset=1;
  1469.           }else{
  1470.             zreg=q1reg;
  1471.           }
  1472.         }
  1473.         continue;
  1474.       }
  1475.     }
  1476.     if(c==KOMPLEMENT){
  1477.       fprintf(f,"\tnor%s\t%s,%s,%s\n",record[setcc],mregnames[zreg],mregnames[q1reg],mregnames[q1reg]);
  1478.       ccset|=setcc;
  1479.       continue;
  1480.     }
  1481.     if(c==SETRETURN){
  1482.       if(p->z.reg){
  1483.         if(zreg==0) load_reg(f,p->z.reg,&p->q1,t,t3);
  1484.       }else
  1485.         ierror(0);
  1486.       continue;
  1487.     }
  1488.     if(c==GETRETURN){
  1489.       if(p->q1.reg)
  1490.         zreg=p->q1.reg;
  1491.       else
  1492.         p->z.flags=0;
  1493.       continue;
  1494.     }
  1495.     if(c==CALL){
  1496.       int reg;
  1497.       ccset=0;
  1498.       if((p->q1.flags&VAR)&&p->q1.v->fi&&p->q1.v->fi->inline_asm){
  1499.         fprintf(f,"%s\n",p->q1.v->fi->inline_asm);
  1500.       }else{
  1501.         if(p->q1.flags&VAR){
  1502.           if(!strcmp("__va_start",p->q1.v->identifier)){
  1503.             fprintf(f,"\taddi\t%s,%s,%ld\n",mregnames[r3],mregnames[sp],framesize+8);
  1504.             continue;
  1505.           }
  1506.           if(!strcmp("__va_regbase",p->q1.v->identifier)){
  1507.             fprintf(f,"\taddi\t%s,%s,%ld\n",mregnames[r3],mregnames[sp],regbase);
  1508.             continue;
  1509.           }
  1510.           if(!strcmp("__va_fixedgpr",p->q1.v->identifier)){
  1511.             fprintf(f,"\tli\t%s,%d\n",mregnames[r3],fixedgpr);
  1512.             continue;
  1513.           }
  1514.           if(!strcmp("__va_fixedfpr",p->q1.v->identifier)){
  1515.             fprintf(f,"\tli\t%s,%d\n",mregnames[r3],fixedfpr);
  1516.             continue;
  1517.           }
  1518.         }
  1519.         if(g_flags[10]&USEDFLAG) fprintf(f,"\tcreqv\t6,6,6\n");
  1520.         if(q1reg){
  1521.           fprintf(f,"\tmtlr\t%s\n",mregnames[q1reg]);
  1522.           fprintf(f,"\tblrl\n");
  1523.         }else{
  1524.           fprintf(f,"\tbl\t");probj2(f,&p->q1,t);
  1525.           fprintf(f,"\n");
  1526.         }
  1527.       }
  1528.       pushed-=zl2l(p->q2.val.vlong);
  1529.       continue;
  1530.     }
  1531.     if((t&NQ)==FLOAT||(t&NQ)==DOUBLE) {fpp="f";fpf=1;} else {fpp="";fpf=0;}
  1532.     if(c==ASSIGN||c==PUSH){
  1533.       if(t==0) ierror(0);
  1534.       if(q1reg){
  1535.         if(c==PUSH){
  1536.           if((t&NQ)==DOUBLE) pushed=(pushed+7)/8*8;
  1537.           fprintf(f,"\tst%s\t%s,%ld(%s)\n",sdt[t&NQ],mregnames[q1reg],pushed+8,mregnames[sp]);
  1538.           pushed+=zl2l(p->q2.val.vlong);
  1539.           continue;
  1540.         }
  1541.         if(c==ASSIGN){
  1542.           if(setcc&&!fpf){
  1543.             fprintf(f,"\tmr.\t%s,%s\n",mregnames[zreg],mregnames[q1reg]);
  1544.             ccset=1;
  1545.           }else{
  1546.             zreg=q1reg;
  1547.           }
  1548.         }
  1549.         continue;
  1550.       }
  1551.     }
  1552.     if(c==ADDRESS){
  1553.       load_address(f,zreg,&p->q1,POINTER);
  1554.       continue;
  1555.     }
  1556.     if(c==MINUS){
  1557.       fprintf(f,"\t%sneg%s\t%s,%s\n",fpp,record[setcc&&!fpf],mregnames[zreg],mregnames[q1reg]);
  1558.       if(setcc&&!fpf) ccset=1;
  1559.       continue;
  1560.     }
  1561.     if(c==TEST){
  1562.       if(!(p->z.flags®))
  1563.         p->z.reg=cr0;
  1564.       if(!multiple_ccs&&(t&UNSIGNED)){
  1565.         struct IC *p2=p->next;
  1566.         while(p2&&(p2->code==FREEREG||p2->code==ALLOCREG)) p2=p2->next;
  1567.         if(!p2||p2->code<BEQ||p2->code>BGT) ierror(0);
  1568.         if(p2->code==BGT) p2->code=BNE;
  1569.         else if(p2->code==BGE) p2->code=BRA;
  1570.         else if(p2->code==BLT) p2->code=NOP;
  1571.         else if(p2->code==BLE) p2->code=BEQ;
  1572.       }
  1573.       if(ccset&&p->z.reg==cr0) continue;
  1574.       if((t&NQ)==FLOAT||(t&NQ)==DOUBLE)
  1575.         ierror(0);
  1576.       else
  1577.         fprintf(f,"\tcmp%swi\t%s,%s,0\n",(t&UNSIGNED)?"l":"",mregnames[p->z.reg],mregnames[q1reg]);
  1578.       if(p->z.reg==cr0) ccset=0;
  1579.       continue;
  1580.     }
  1581.     if(c==COMPARE){
  1582.       if(!(p->z.flags®))
  1583.         p->z.reg=cr0;
  1584.       if((t&NQ)==FLOAT||(t&NQ)==DOUBLE)
  1585.         fprintf(f,"\tfcmpu\t%s,%s,",mregnames[p->z.reg],mregnames[q1reg]);
  1586.       else
  1587.         fprintf(f,"\tcmp%sw%s\t%s,%s,",(t&UNSIGNED)?"l":"",isimm[q2reg==0],mregnames[p->z.reg],mregnames[q1reg]);
  1588.       probj2(f,&p->q2,t);fprintf(f,"\n");
  1589.       if(p->z.reg==cr0) ccset=0;
  1590.       continue;
  1591.     }
  1592.     if(c==AND&&q2reg==0){
  1593.       ccset=setcc;
  1594.       fprintf(f,"\tandi.\t%s,%s,",mregnames[zreg],mregnames[q1reg]);
  1595.       probj2(f,&p->q2,t|UNSIGNED);fprintf(f,"\n");
  1596.       continue;
  1597.     }
  1598.     if(c>=OR&&c<=AND){
  1599.       fprintf(f,"\t%s%s%s\t%s,%s,",logicals[c-OR],isimm[q2reg==0],record[setcc&&q2reg],mregnames[zreg],mregnames[q1reg]);
  1600.       probj2(f,&p->q2,t|UNSIGNED);fprintf(f,"\n");
  1601.       if(setcc&&q2reg) ccset=1;
  1602.       continue;
  1603.     }
  1604.     if(c==SUB&&(p->q1.flags&KONST)){
  1605.       fprintf(f,"\tsubfic\t%s,%s,",mregnames[zreg],mregnames[q2reg]);
  1606.       probj2(f,&p->q1,t&NQ);fprintf(f,"\n");
  1607.       continue;
  1608.     }
  1609.     if(c>=LSHIFT&&c<=MOD){
  1610.       if(c==RSHIFT&&!(t&UNSIGNED)){
  1611.         fprintf(f,"\tsraw%s%s\t%s,%s,",isimm[q2reg==0],record[setcc],mregnames[zreg],mregnames[q1reg]);
  1612.         probj2(f,&p->q2,t); fprintf(f,"\n");
  1613.         ccset|=setcc;
  1614.         continue;
  1615.       }
  1616.       if(c==MOD){
  1617.         i=0;
  1618.         if(zreg==q1reg||zreg==q2reg){
  1619.           if(t1!=q1reg&&t1!=q2reg) i=t1;
  1620.           if(t2!=q1reg&&t2!=q2reg) i=t2;
  1621.         }else i=zreg;
  1622.         if(i==0||i==q1reg||i==q2reg) ierror(0);
  1623.         fprintf(f,"\tdivw%s\t%s,%s,%s\n",(t&UNSIGNED)?"u":"",mregnames[i],mregnames[q1reg],mregnames[q2reg]);
  1624.         fprintf(f,"\tmullw\t%s,%s,%s\n",mregnames[i],mregnames[i],mregnames[q2reg]);
  1625.         fprintf(f,"\tsubf%s\t%s,%s,%s\n",record[setcc],mregnames[zreg],mregnames[i],mregnames[q1reg]);
  1626.         ccset|=setcc;
  1627.         continue;
  1628.       }
  1629.       if(c==DIV&&(t&UNSIGNED)){
  1630.         fprintf(f,"\tdivwu%s%s\t%s,%s,",isimm[q2reg==0],record[setcc&&q2reg],mregnames[zreg],mregnames[q1reg]);
  1631.         if(setcc&&q2reg) ccset=1;
  1632.       }else if(c==MULT&&((t&NQ)==FLOAT||(t&NQ)==DOUBLE)){
  1633.         fprintf(f,"\tfmul%s\t%s,%s,",record[setcc],mregnames[zreg],mregnames[q1reg]);
  1634.         ccset|=setcc;
  1635.       }else if(c==DIV&&((t&NQ)==FLOAT||(t&NQ)==DOUBLE)){
  1636.         fprintf(f,"\tfdiv%s\t%s,%s,",record[setcc],mregnames[zreg],mregnames[q1reg]);
  1637.         ccset|=setcc;
  1638.       }else if(c==MULT&&q2reg==0){
  1639.         fprintf(f,"\tmulli\t%s,%s,",mregnames[zreg],mregnames[q1reg]);
  1640.       }else if(c==ADD&&setcc&&!q2reg){
  1641.         fprintf(f,"\taddic.\t%s,%s,",mregnames[zreg],mregnames[q1reg]);
  1642.         ccset=1;
  1643.       }else{
  1644.         fprintf(f,"\t%s%s%s%s\t%s,%s,",fpp,arithmetics[c-LSHIFT],isimm[q2reg==0],record[setcc&&q2reg&&!fpf],mregnames[zreg],mregnames[q1reg]);
  1645.         if(setcc&&q2reg&&!fpf) ccset=1;
  1646.       }
  1647.       probj2(f,&p->q2,t&NQ);fprintf(f,"\n");
  1648.       continue;
  1649.     }
  1650.     ierror(0);
  1651.   }
  1652.   lastlabel=label;
  1653.   free(once);free(twice);
  1654.   function_bottom(f,v,of);
  1655. }
  1656.  
  1657. int shortcut(int code,int typ)
  1658. {
  1659.   return(0);
  1660. }
  1661.  
  1662. int reg_parm(struct reg_handle *m, struct Typ *t)
  1663. {
  1664.   int f;
  1665.   if(!m) ierror(0);
  1666.   if(!t) ierror(0);
  1667.   f=t->flags&NQ;
  1668.   if(f<=LONG||f==POINTER){
  1669.     if(m->gregs>=8) return(0);
  1670.     return(r3-m->gregs++);
  1671.   }
  1672.   if(f==FLOAT||f==DOUBLE){
  1673.     if(m->fregs>=8) return(0);
  1674.     return(46-m->fregs++);
  1675.   }
  1676.   return(0);
  1677. }
  1678. void cleanup_cg(FILE *f)
  1679. {
  1680.   struct fpconstlist *p;
  1681.   unsigned char *ip;
  1682.   while(p=firstfpc){
  1683.     if(f){
  1684.       if(section!=RODATA){fprintf(f,rodataname);section=RODATA;}
  1685.       if((p->typ&NQ)==DOUBLE)
  1686.         fprintf(f,"\t.align\t3\n");
  1687.       else
  1688.         fprintf(f,"\t.align\t2\n");
  1689.       fprintf(f,"%s%d:\n\t.long\t",labprefix,p->label);
  1690.       ip=(unsigned char *)&p->val.vdouble;
  1691.       fprintf(f,"0x%02x%02x%02x%02x",ip[0],ip[1],ip[2],ip[3]);
  1692.       if((p->typ&NQ)==DOUBLE){
  1693.         fprintf(f,",0x%02x%02x%02x%02x",ip[4],ip[5],ip[6],ip[7]);
  1694.       }
  1695.       fprintf(f,"\n");
  1696.     }
  1697.     firstfpc=p->next;
  1698.     free(p);
  1699.   }
  1700. }
  1701.  
  1702.  
  1703.